<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>terms 聚合 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'search-aggregations-bucket-terms-aggregation.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-bucket-terms-aggregation.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-bucket-terms-aggregation.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/search-aggregations-bucket-terms-aggregation.html" rel="nofollow" target="_blank">../en/search-aggregations-bucket-terms-aggregation.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations.html">聚合</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations-bucket.html">桶(bucket)聚合</a></span>
»
<span class="breadcrumb-node">terms 聚合</span>
</div>
<div class="navheader">
<span class="prev">
<a href="search-aggregations-bucket-significanttext-aggregation.html">« significant_text 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-bucket-range-field-note.html">给范围字段分桶的微妙之处 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="search-aggregations-bucket-terms-aggregation"></a>词项(terms)聚合
</h2>
</div></div></div>
<p>一种基于多桶值源的聚合，其中桶是用一个个的唯一值动态构建的。</p>
<p>示例：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : { "field" : "genre" } <a id="CO242-1"></a><i class="conum" data-value="1"></i>
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/522.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO242-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>
<code class="literal">terms</code>聚合应该是<code class="literal">keyword</code>类型的字段或任何其他适合于桶聚合的数据类型。

为了与<code class="literal">text</code>一起使用，需要启用<a class="xref" href="fielddata.html" title="fielddata" rel="nofollow">fielddata</a>。
</p>
</td>
</tr>
</table>
</div>
<p>响应：</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
    ...
    "aggregations" : {
        "genres" : {
            "doc_count_error_upper_bound": 0, <a id="CO243-1"></a><i class="conum" data-value="1"></i>
            "sum_other_doc_count": 0, <a id="CO243-2"></a><i class="conum" data-value="2"></i>
            "buckets" : [ <a id="CO243-3"></a><i class="conum" data-value="3"></i>
                {
                    "key" : "electronic",
                    "doc_count" : 6
                },
                {
                    "key" : "rock",
                    "doc_count" : 3
                },
                {
                    "key" : "jazz",
                    "doc_count" : 2
                }
            ]
        }
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO243-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>每个词项的文档计数的误差上限，见<a class="xref" href="search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-approximate-counts" title="Document counts are approximate">下文</a>
</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO243-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>当有很多唯一的词时，Elasticsearch只返回前面几个词；此数字是不属于响应的所有桶的文档计数总和</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO243-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>前几个(top)桶的列表，<code class="literal">top</code>是由<a class="xref" href="search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-order" title="Order">order</a>定义的</p>
</td>
</tr>
</table>
</div>
<p>
默认情况下，<code class="literal">terms</code>聚合将返回按<code class="literal">doc_count</code>排序的前10个词的桶。

可以通过设置参数<code class="literal">size</code>来改变这种默认行为。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-size"></a>size
</h3>
</div></div></div>
<p>
参数<code class="literal">size</code>可以用来定义应该从整个词项列表中返回多少个词项桶。

默认情况下，协调搜索过程的节点(被称为协调节点)将请求每个分片提供其自己的前<code class="literal">size</code>个词项桶，并且一旦所有分片做出响应，它将把结果缩小到最终列表，然后将该列表返回给客户端。

这意味着，如果唯一词的数量大于<code class="literal">size</code>，则返回的列表会稍有偏差且不准确(可能是词项计数稍有偏差，甚至可能是本应该在前 size 个桶中的项没有返回)。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
如果你想要检索嵌套<code class="literal">terms</code>聚合中的<span class="strong strong"><strong>所有</strong></span>词项或所有词项组合，应该使用<a class="xref" href="search-aggregations-bucket-composite-aggregation.html" title="composite聚合">composite</a>聚合，它允许对所有可能的词项进行分页，而不是将size设置为大于<code class="literal">terms</code>聚合中字段的基数。

<code class="literal">terms</code>聚合旨在返回<code class="literal">top</code>(前几个)词项，不允许分页。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-approximate-counts"></a>文档计数是近似值
</h3>
</div></div></div>
<p>
terms 聚合中的文档计数(以及任何子聚合的结果)并不总是准确的。

每一个分片都提供了自己的 terms 排序列表视图。

这些视图被组合起来以给出最终视图。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_shard_size_3"></a>分片大小(shard_size)
</h3>
</div></div></div>
<p>请求的<code class="literal">size</code>越高，结果就越准确，但是计算最终结果的成本也就越高(这是因为在分片级别上管理的优先级队列越大，以及节点和客户端之间传输的数据越多)。</p>
<p>
参数<code class="literal">shard_size</code>可用于最小化因请求的<code class="literal">size</code>较大而带来的额外工作。

一旦定义了，它将决定协调节点将从每个分片请求多少个词项。

一旦所有的分片都作出响应，协调节点就会将它们缩小到基于参数<code class="literal">size</code>的最终结果——通过这种方式，可以提高返回项的准确性，并避免将一个大的桶列表流回客户端的开销。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p><code class="literal">shard_size</code> 不能小于<code class="literal">size</code>(因为没有太大意义)。当它存在时，Elasticsearch将覆盖它并将其重置为与<code class="literal">size</code>相等。</p>
</div>
</div>
<p><code class="literal">shard_size</code> 的默认值为 <code class="literal">(size * 1.5 + 10)</code>。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_calculating_document_count_error"></a>当计算文档数量有误差时
</h3>
</div></div></div>
<p>
在 terms 聚合中可以显示两个误差值。

第一个给出了聚合的整体值，该值表示没有进入最终词项列表的词项的最大潜在文档数。

它被计算为从每个分片返回的最后一个词项的文档计数的总和。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_per_bucket_document_count_error"></a>单个桶的文档数量计算有误差
</h3>
</div></div></div>
<p>通过将<code class="literal">show_term_doc_count_error</code>参数设置为true，可以启用第二个误差值：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "products" : {
            "terms" : {
                "field" : "product",
                "size" : 5,
                "show_term_doc_count_error": true
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/523.console"></div>
<p>
这显示了聚合返回的每个词项的误差值，它代表了文档计数中<em>最差情况</em>的误差，在决定<code class="literal">shard_size</code>参数的值时非常有用。

这是通过对没有返回词项的所有分片返回的最后一个词项的文档计数求和来计算的。
</p>
<p>
只有当词项按文档计数降序排列时，才能以这种方式计算这些误差。

当聚合按词项值本身排序(升序或降序)时，在文档计数中没有误差，因为如果一个分片没有返回出现在另一个分片的结果中的特定词项，则它的索引中一定没有该词项。

当聚合按子聚合或按文档计数升序排序时，无法确定文档计数中的误差，并给定一个值 -1 来表示这一点。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-order"></a>排序(order)

</h3>
</div></div></div>
<p>
可以通过设置参数<code class="literal">order</code>来指定桶的顺序。

默认情况下，桶按照<code class="literal">doc_count</code>降序排列。

有可能改变这种行为，如下所示：
</p>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>
不鼓励使用<code class="literal">_count</code>升序或子查询进行排序，因为这会增加文档计数的<a class="xref" href="search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-approximate-counts" title="Document counts are approximate">误差</a>。

当查询单个分片时，或者当被聚集的字段在索引时被用作路由键时，这是没有问题的:在这些情况下，结果将是准确的，因为分片具有不相交的值。

然而，除此之外，误差是没有上限的。

仍然有用的一种特殊情况是按<a class="xref" href="search-aggregations-metrics-min-aggregation.html" title="min 聚合"><code class="literal">min</code></a>或<a class="xref" href="search-aggregations-metrics-max-aggregation.html" title="max 聚合"><code class="literal">max</code></a>聚合排序：计数不准确，但至少会正确选择最前面的几个桶。
</p>
</div>
</div>
<p>将桶按文档的<code class="literal">_count</code>升序排序：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "_count" : "asc" }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/524.console"></div>
<p>将桶按按词项的字母顺序的升序排序：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "_key" : "asc" }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/525.console"></div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<h3>在6.0.0版本中废弃</h3>
<p>使用<code class="literal">_key</code>代替<code class="literal">_term</code>，将桶按词项排序</p>
</div>
</div>
<p>按单值度量子聚合对桶进行排序(由聚合名称标识)：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "max_play_count" : "desc" }
            },
            "aggs" : {
                "max_play_count" : { "max" : { "field" : "play_count" } }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/526.console"></div>
<p>按多值度量子聚集对桶进行排序(由聚合名称标识)：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "playback_stats.max" : "desc" }
            },
            "aggs" : {
                "playback_stats" : { "stats" : { "field" : "play_count" } }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/527.console"></div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<h3>管道(pipeline)聚合不能用于排序</h3>
<p>
<a class="xref" href="search-aggregations-pipeline.html" title="Pipeline Aggregations">管道(pipeline)聚合</a>在所有其他聚合完成后的压缩阶段运行。

因此，它们不能用于排序。
</p>
</div>
</div>
<p>
还可以根据层次结构中“更深”的聚合对桶进行排序。

只要聚合路径是单桶类型，就支持这一点，其中路径中的最后一个聚合可以是单桶聚合，也可以是度量聚合。

如果是单桶类型，则顺序将由桶中的文档数(即<code class="literal">doc_count</code>)来定义，如果是度量类型，则应用与上述相同的规则(如果是多值度量聚合，则路径必须指示要排序的度量名称，如果是单值度量聚合，则排序将应用于该值)。
</p>
<p>路径必须按以下形式定义：</p>
<div class="pre_wrapper lang-ebnf">
<pre class="programlisting prettyprint lang-ebnf">AGG_SEPARATOR       =  '&gt;' ;
METRIC_SEPARATOR    =  '.' ;
AGG_NAME            =  &lt;the name of the aggregation&gt; ;
METRIC              =  &lt;the name of the metric (in case of multi-value metrics aggregation)&gt; ;
PATH                =  &lt;AGG_NAME&gt; [ &lt;AGG_SEPARATOR&gt;, &lt;AGG_NAME&gt; ]* [ &lt;METRIC_SEPARATOR&gt;, &lt;METRIC&gt; ] ;</pre>
</div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "countries" : {
            "terms" : {
                "field" : "artist.country",
                "order" : { "rock&gt;playback_stats.avg" : "desc" }
            },
            "aggs" : {
                "rock" : {
                    "filter" : { "term" : { "genre" :  "rock" }},
                    "aggs" : {
                        "playback_stats" : { "stats" : { "field" : "play_count" }}
                    }
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/528.console"></div>
<p>上面的查询将根据摇滚歌曲的平均播放次数对 艺术家的国家(artist.country) 进行分类。</p>
<p>通过提供一组排序标准，可以使用多个标准来对桶进行排序，如下所示：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "countries" : {
            "terms" : {
                "field" : "artist.country",
                "order" : [ { "rock&gt;playback_stats.avg" : "desc" }, { "_count" : "desc" } ]
            },
            "aggs" : {
                "rock" : {
                    "filter" : { "term" : { "genre" : "rock" }},
                    "aggs" : {
                        "playback_stats" : { "stats" : { "field" : "play_count" }}
                    }
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/529.console"></div>
<p>
上面的查询将根据摇滚歌曲的 平均播放次数(playback_stats.avg)，然后按照<code class="literal">doc_count</code>降序排列 艺术家的国家(artist.country) 类别。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>如果两个桶在所有排序标准中共享相同的值，则将再按桶的词项值升序排序，以防止桶的不确定性排序。</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_minimum_document_count_4"></a>最小文档数量
</h3>
</div></div></div>
<p>使用<code class="literal">min_doc_count</code>选项可以只返回匹配超过配置的命中数的词项：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "min_doc_count": 10
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/530.console"></div>
<p>上述聚集将仅返回有10次或更多次命中出现的 tags。默认值为<code class="literal">1</code>。</p>
<p>
词项在分片级别上被收集和排序，并在第二步中与从其他分片收集的词项合并。

然而，分片没有关于可用的全局词项计数的信息。

是否将一个词项添加到候选列表的决定只取决于使用局部分片频率在分片上计算的排序。

<code class="literal">min_doc_count</code>标准仅在合并所有分片的本地词项统计之后应用。

在某种程度上，在没有非常<em>确定</em>该词项是否将实际达到所需的<code class="literal">min_doc_count</code>的情况下，就做出了将该词项添加为候选项的决定。

如果低频的词项填充了候选列表，这可能导致许多(全局)高频的词项在最终结果中丢失。

为了避免这种情况，可以增加<code class="literal">shard_size</code>参数，以允许分片上有更多的候选项。

但是，这会增加内存消耗和网络流量。
</p>
<p>参数<code class="literal">shard_min_doc_count</code></p>
<p>
参数<code class="literal">shard_min_doc_count</code>规定了一个分片相对于<code class="literal">min_doc_count</code>是否应该被实际添加到候选列表中的<em>确定性</em>。

只有当词项在集合中的本地分片频率高于<code class="literal">shard_min_doc_count</code>时，才会考虑这些词项。

如果你的字典包含许多低频的单词，而你对这些单词不感兴趣(例如拼写错误)，那么你可以设置<code class="literal">shard_min_doc_count</code>参数来过滤掉分级别上的候选词，即使在合并本地频率之后，这些候选词也肯定不会达到所需的<code class="literal">min_doc_count</code>。 

默认情况下，<code class="literal">shard_min_doc_count</code>设置为<code class="literal">0</code>，除非你显式设置它，否则它不起作用。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
设置<code class="literal">min_doc_count</code>=<code class="literal">0</code>也还是会返回不匹配任何匹配项的桶。

但是，某些返回的文档计数为零的词项可能只属于已删除的文档或其他类型的文档，因此不能保证<code class="literal">match_all</code>查询会为这些词项找到正的文档计数。
</p>
</div>
</div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>
当不对<code class="literal">doc_count</code>进行降序排序时，<code class="literal">min_doc_count</code>的高值可能会返回小于<code class="literal">size</code>的桶数，因为没有从分片中收集足够的数据。

将<code class="literal">shard_min_doc_count</code>设置得太高会导致词项在分片级别被过滤掉。

该值应设置为远低于<code class="literal">min_doc_count/#shards</code>。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-script"></a>脚本
</h3>
</div></div></div>
<p>使用脚本生成一个词：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "script" : {
                    "source": "doc['genre'].value",
                    "lang": "painless"
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/531.console"></div>
<p>这将把<code class="literal">script</code>参数解释为使用默认脚本语言且没有脚本参数的 <code class="literal">内联(inline)</code>脚本。要使用存储的脚本，请使用以下语法：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "script" : {
                    "id": "my_script",
                    "params": {
                        "field": "genre"
                    }
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/532.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_value_script_9"></a>值脚本(value script)
</h3>
</div></div></div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "script" : {
                    "source" : "'Genre: ' +_value",
                    "lang" : "painless"
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/533.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_filtering_values_4"></a>对值进行过滤
</h3>
</div></div></div>
<p>
可以过滤将用于创建桶的值。

这可以使用基于正则表达式字符串或精确值数组的<code class="literal">include</code>和<code class="literal">exclude</code>参数来完成。

此功能反映了 terms 聚合文档中描述的功能。

此外，<code class="literal">include</code>子句可以使用<code class="literal">partition</code>表达式进行过滤。
</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_filtering_values_with_regular_expressions_2"></a>使用正则表达式对值进行过滤
</h4>
</div></div></div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "include" : ".*sport.*",
                "exclude" : "water_.*"
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/534.console"></div>
<p>
在上面的例子中，将为所有包含单词<code class="literal">sport</code>的 tags 创建桶，除了那些以<code class="literal">water_</code>开头的标签(因此值为<code class="literal">water_sports</code>的 tag 不会被聚合)。

<code class="literal">include</code>正则表达式将决定“允许”聚合哪些值，而<code class="literal">exclude</code>将决定不应该聚合的值。

当二者都被定义时，<code class="literal">exclude</code>优先，这意味着首先计算<code class="literal">include</code>，然后才计算<code class="literal">exclude</code>。
</p>
<p>语法同 <a class="xref" href="regexp-syntax.html" title="正则表达式语法">正则查询</a>。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_filtering_values_with_exact_values_2"></a>使用精确值对值进行过滤
</h4>
</div></div></div>
<p>对于基于精确值的匹配，<code class="literal">include</code>和<code class="literal">exclude</code>参数可以简单地接受一个字符串数组，这些字符串表示在索引中找到的词项：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "JapaneseCars" : {
             "terms" : {
                 "field" : "make",
                 "include" : ["mazda", "honda"]
             }
         },
        "ActiveCarManufacturers" : {
             "terms" : {
                 "field" : "make",
                 "exclude" : ["rover", "jensen"]
             }
         }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/535.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_filtering_values_with_partitions"></a>使用partition对值进行过滤
</h4>
</div></div></div>
<p>
有时在一个请求/响应对中需要处理非常多独特的词，因此将分析分成多个请求会很有用。

这可以通过在查询时将字段值分组到多个 partition(分区) 中，并在每个请求中只处理一个  partition(分区) 来实现。

看一下下面这个请求，它寻找最近没有任何访问记录的帐户：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
   "size": 0,
   "aggs": {
      "expired_sessions": {
         "terms": {
            "field": "account_id",
            "include": {
               "partition": 0,
               "num_partitions": 20
            },
            "size": 10000,
            "order": {
               "last_access": "asc"
            }
         },
         "aggs": {
            "last_access": {
               "max": {
                  "field": "access_date"
               }
            }
         }
      }
   }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/536.console"></div>
<p>
此请求是为了查找客户帐户子集记录的最后访问日期，因为我们可能希望终止一些很久没有出现的客户帐户。

<code class="literal">num_partitions</code>设置要求将唯一的 account_ids 平均组织成20个分区(0到19)。

并且该请求中的<code class="literal">partition</code>设置对仅考虑落入分区0的account_ids进行过滤。

后续请求应该请求分区1、分区2等，以完成堆过期帐户的分析。 
</p>
<p>
注意，返回结果数量的<code class="literal">size</code>设置需要和<code class="literal">num_partitions</code>一起调整。

对于这个特定的帐户到期的例子，平衡<code class="literal">size</code>和<code class="literal">num_partitions</code>值的过程如下:
</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
使用<code class="literal">cardinality</code>聚合来估计唯一 account_id 值的总数
</li>
<li class="listitem">
为<code class="literal">num_partitions</code>选择一个值，将数字从 1) 分成更易于管理的块
</li>
<li class="listitem">
为我们希望从每个分区得到的响应数量选择一个<code class="literal">size</code>值
</li>
<li class="listitem">
运行一个请求做测试
</li>
</ol>
</div>
<p>
如果我们试图在一个请求中做太多事情而遇到断路器错误，则必须增加<code class="literal">num_partitions</code>。

如果请求成功，但按日期排序的测试响应中的最后一个帐户ID仍然是我们可能想要过期的帐户，那么我们可能会错过感兴趣的帐户，而且我们可能将这个数字设置得太低了。

以下必须二选一：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
增加参数<code class="literal">size</code>的值以让每个分区返回更多结果(可能会占用大量内存)，或者
</li>
<li class="listitem">
增加<code class="literal">num_partitions</code>以减少每个请求的帐户数量(可能会增加总处理时间，因为我们需要发出更多的请求)
</li>
</ul>
</div>
<p>最终，这是在管理处理单个请求所需的Elasticsearch资源和客户端应用程序为完成任务必须发出的请求量之间的一个平衡。</p>
</div>

</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_multi_field_terms_aggregation"></a>多个字段词项聚合(Multi-field terms aggregation)
</h3>
</div></div></div>
<p>
<code class="literal">terms</code>聚合不支持从同一文档中的多个字段收集词项。

原因是<code class="literal">terms</code>聚合本身并不收集字符串词项值，而是使用<a class="xref" href="search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-execution-hint" title="执行提示">全局序号(global ordinals)</a>来生成字段中所有唯一值的列表。

全局序号(global ordinals)可以带来重要的性能提升，这在多个字段中是不可能实现的。
</p>
<p>有两种方法可用于跨多个字段执行<code class="literal">terms</code>聚合：</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<a class="xref" href="search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-script" title="Script">脚本</a>
</span>
</dt>
<dd>
使用脚本从多个字段中检索词项。

这将禁用全局序号优化，并且比从单个字段中收集词项要慢，但它为你提供了在搜索时实现此选项的灵活性。
</dd>
<dt>
<span class="term">
<a class="xref" href="copy-to.html" title="copy_to"><code class="literal">copy_to</code>字段</a>
</span>
</dt>
<dd>
如果你事先知道要从两个或更多字段中收集词项，那么可以在映射中使用<code class="literal">copy_to</code>在编制索引时创建一个新的专用字段，其中包含两个字段的值。

可以在这个单一字段上进行聚合，而这将可以利用全局序号优化带来的好处。 
</dd>
</dl>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-collect"></a>收集模式
</h3>
</div></div></div>
<p>推迟子聚合的计算</p>
<p>
对于具有许多唯一词项和少量必需结果的字段，将子聚合的计算延迟到顶层父级聚合被删除后进行可能会更有效。

通常，聚合树的所有分支都在一次深度优先的遍历中展开，然后才进行任何修剪。

在某些情况下，这可能是非常浪费的，并且会达到内存限制。

一个此类问题场景的例子是在电影数据库中查询10个最受欢迎的演员和他们的5个最常见的联合主演:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "actors" : {
             "terms" : {
                 "field" : "actors",
                 "size" : 10
             },
            "aggs" : {
                "costars" : {
                     "terms" : {
                         "field" : "actors",
                         "size" : 5
                     }
                 }
            }
         }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/537.console"></div>
<p>
尽管参与者的数量可能相对较少，我们只需要50个结果桶，但是在计算过程中会出现桶的组合爆炸——一个参与者可以产生 n² 个桶（其中n是参与者的数量）。

明智的选择是首先确定10个最受欢迎的演员，然后才检查这10个演员的最佳联合主演。

这种替代策略就是我们所说的<code class="literal">广度优先(breadth_first)</code>收集模式，与 <code class="literal">深度优先(depth_first)</code>模式相对。
</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
<code class="literal">广度优先(breadth_first)</code>是基数大于请求大小的字段或基数未知的字段(例如数值字段或脚本)的默认模式。

可以覆盖默认启发式规则，并在请求中直接指定收集模式：
</p>
</div>
</div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "actors" : {
             "terms" : {
                 "field" : "actors",
                 "size" : 10,
                 "collect_mode" : "breadth_first" <a id="CO244-1"></a><i class="conum" data-value="1"></i>
             },
            "aggs" : {
                "costars" : {
                     "terms" : {
                         "field" : "actors",
                         "size" : 5
                     }
                 }
            }
         }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/538.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO244-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>可能的值是<code class="literal">breadth_first</code>和<code class="literal">depth_first</code></p>
</td>
</tr>
</table>
</div>
<p>
当使用<code class="literal">广度优先(breadth_first)</code>模式时，落入最主要的桶中的文档集被缓存以供后续重放，因此这样做存在与匹配文档的数量成线性关系的内存开销。

请注意，在使用<code class="literal">breadth_first</code>设置时，参数<code class="literal">order</code>仍可用于引用子聚合中的数据——父聚合知道需要在调用任何其他子聚合之前首先调用该子聚合。
</p>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>诸如<code class="literal">top_hits</code>之类的嵌套聚合，需要访问使用<code class="literal">breadth_first</code>收集模式的聚合下的得分信息，需要在第二次传递时重放查询，但只针对属于前几个桶的文档。</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="search-aggregations-bucket-terms-aggregation-execution-hint"></a>执行提示（execution hint）
</h3>
</div></div></div>
<p>可以通过不同的机制来执行 terms 聚合：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
通过直接使用字段值来聚合每个桶的数据 (<code class="literal">map</code>)
</li>
<li class="listitem">
通过使用字段的全局序号并为每个全局序号分配一个桶 (<code class="literal">global_ordinals</code>)
</li>
</ul>
</div>
<p>Elasticsearch试图使用合理的默认值，所以这通常不需要配置。</p>
<p><code class="literal">global_ordinals</code>是<code class="literal">keyword</code>类型字段的默认选项，它使用全局序号来动态分配桶，因此内存使用量与聚合范围内的文档值的数量成线性关系。</p>
<p>只有当很少文档与查询匹配时，才应该考虑<code class="literal">map</code>。默认情况下，<code class="literal">map</code>仅在脚本上运行聚合时使用，因为它们没有序号。</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "tags" : {
             "terms" : {
                 "field" : "tags",
                 "execution_hint": "map" <a id="CO245-1"></a><i class="conum" data-value="1"></i>
             }
         }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/539.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO245-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>可能的值是<code class="literal">map</code>、<code class="literal">global_ordinals</code></p>
</td>
</tr>
</table>
</div>
<p>请注意，如果这个执行提示不适用，并且对这些提示没有向后兼容性保证，Elasticsearch将忽略它。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_missing_value_17"></a>缺失的值
</h3>
</div></div></div>
<p>参数<code class="literal">missing</code>定义应该如何处理缺少值的文档。默认情况下，它们将被忽略，但也可以将它们视为有一个值。</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "aggs" : {
        "tags" : {
             "terms" : {
                 "field" : "tags",
                 "missing": "N/A" <a id="CO246-1"></a><i class="conum" data-value="1"></i>
             }
         }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/540.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO246-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">tags</code>字段中没有值的文档将与具有<code class="literal">N/A</code>值的文档落入同一个桶中。</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_mixing_field_types"></a>混合字段类型
</h3>
</div></div></div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>
在多个索引上执行聚合时，所有索引中聚合字段的类型可能不相同。

有些类型是相互兼容的(<code class="literal">integer</code>和<code class="literal">long</code>，<code class="literal">float</code>和<code class="literal">double</code>)，但是当类型是十进制数和非十进制数的混合时，terms 聚合会将非十进制数转换为十进制数。

这可能会导致桶值的精度损失。
</p>
</div>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="search-aggregations-bucket-significanttext-aggregation.html">« significant_text 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-bucket-range-field-note.html">给范围字段分桶的微妙之处 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>